﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;

namespace Vortex {

	/// <summary>
	/// Implementation of game window object
	/// </summary>
	public sealed class GameWindow {
		private Form _form;
		private Size _size;
		private bool _fullscreen;
		private bool _verticalSync;
		private bool _resetRequired;
		private bool _cursorHidden;

		///<summary>True when window is foreground and active</summary>
		private bool _active;

		#region Private Stuff

		/// <summary>
		/// Resizes the window with specified new size.
		/// </summary>
		/// <param name="newSize">The new size.</param>
		private void Resize(Size newSize) {
			if (newSize.Width >= 1 || newSize.Height >= 1) {
				_size = newSize;
				_form.ClientSize = newSize;
				_resetRequired = true;
			} else {
				throw new ArgumentException("Game window size should be less than 1", "size");
			}

			
		}

		#endregion


		/// <summary>
		/// Custom GameForm class for setting custom control styles
		/// </summary>
		class GameForm : Form {
			public GameForm() {
				//it is important to make window paint events in base manner
				SetStyle(ControlStyles.AllPaintingInWmPaint, true);
				SetStyle(ControlStyles.UserPaint, true);
				SetStyle(ControlStyles.Opaque, true);
				SetStyle(ControlStyles.ResizeRedraw, false);
			}
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="GameWindow"/> class.
		/// </summary>
		internal GameWindow() {
			_form = new GameForm();
			_form.Deactivate += delegate(object sender, EventArgs args) { _active = false; };
			_form.Activated += delegate(object sender, EventArgs args) { _active = true; };
		}

		/// <summary>
		/// Gets the form instances.
		/// </summary>
		/// <value>The form instance.</value>
		internal Form Form {
			get { return _form; }
		}

		/// <summary>
		/// Gets or sets a value indicating whether game device reset is required.
		/// </summary>
		/// <value>
		/// 	<c>true</c> if game device reset is required; otherwise, <c>false</c>.
		/// </value>
		internal bool IsResetRequired {
			get { return _resetRequired; }
			set { _resetRequired = value; }
		}

		/// <summary>
		/// Updates this window.
		/// </summary>
		internal void Update() {
			if (_fullscreen) {
				_form.FormBorderStyle = FormBorderStyle.None;
			} else {
				_form.FormBorderStyle = FormBorderStyle.FixedSingle;
				_form.MaximizeBox = false;
				_form.ShowIcon = false;
			}

			_form.ClientSize = _size;
			_form.Show();
			_form.Update();
		}

		internal void OnReset() {
			Update();
			_resetRequired = false;			
		}

		internal void Destroy() {
			_form.Dispose();
		}

		#region Public Interface

		/// <summary>
		/// Gets the handle of the window.
		/// </summary>
		/// <value>The handle of the window.</value>
		public IntPtr Handle {
			get { return _form.Handle; }
		}

		/// <summary>
		/// Gets or sets the title of window.
		/// </summary>
		/// <value>The title of window.</value>
		public string Title {
			get { return _form.Text; }
			set { _form.Text = value; }
		}

		/// <summary>
		/// Gets or sets the location of the window on desktop.
		/// </summary>
		/// <value>The location of the window on desktop.</value>
		public Point Location {
			get { return _form.Location; }
			set { _form.Location = value; }
		}

		/// <summary>
		/// Gets or sets the size of window client area.
		/// </summary>
		/// <value>The size of window client area.</value>
		public Size Size {
			get { return _size; }
			set {
				if (!value.Equals(_size)) {
					Resize(value);
				}
			}
		}

		/// <summary>
		/// Gets or sets a value indicating whether this <see cref="GameWindow"/> is fullscreen.
		/// </summary>
		/// <value><c>true</c> if fullscreen; otherwise, <c>false</c>.</value>
		public bool Fullscreen {
			get { return _fullscreen; }
			set {
				if (_fullscreen != value) {
					_fullscreen = value;
					_resetRequired = true;
				}
			}
		}

		/// <summary>
		/// Gets or sets a value indicating whether vertical sync is enabled.
		/// </summary>
		/// <value><c>true</c> if vertical sync is enabled; otherwise, <c>false</c>.</value>
		public bool VerticalSync {
			get { return _verticalSync; }
			set {
				if (_verticalSync != value) {
					_verticalSync = value;
					_resetRequired = true;
				}
			}
		}

		/// <summary>
		/// Locates window at the desktop center.
		/// </summary>
		public void LocateAtDesktopCenter() {
			//find current screen where form is located
			Screen screen = Screen.FromControl(_form);
			Rectangle screenArea = screen.WorkingArea;
			Size screenSize = screenArea.Size;
			//move window
			Location = new Point(
				screenArea.X + (screenSize.Width - _form.Width) / 2,
				screenArea.Y + (screenSize.Height - _form.Height) / 2
			);
		}

		#endregion

		internal void HideCursor() {
			if (!_cursorHidden) {
				Cursor.Hide();
				_cursorHidden = true;
			}
		}

		internal void ShowCursor() {
			Cursor.Show();
			_cursorHidden = false;
		}

	}

}
